﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using HPPUtil;
using FastReflectionLib;
using System.Net;

namespace HPPClientLibrary
{
    /// <summary>
    /// 配置文件操作类
    /// </summary>
    public class ConfigManager : PropertyChangedBase
    {
        #region Fields

        public static readonly string SectionName = "Config";
        private static List<PropertyInfo> _toSavePropertyList;
        private static object _syncRoot = new object();
        public static readonly int DownloadManagerTimerInterval = 1000;//单位为：毫秒
        public static readonly string ConfigFolder = "Config";
        public static readonly string ConfigFileName = "Config.ini";
        

        #region Save Fields

        private int _totalThreadLimit;
        private int _jobThreadLimit;
        private int _smartThreadPoolTimeOut;
        private int _getPeerListInterval;//单位为：毫秒
        private int _clearDisableIPListInterval;//单位为：毫秒
        private int _bufferSizePerJob;
        private int _totalBufferSize;
        private int _ipRetryCount;
        private IPEndPoint _serverIP;
        private string _saveFilePath = "Download";
        private int _CSServerPort = 9995;
        private string _SSServerIP = "127.0.0.0";
        private int _SSServerPort = 9999;
        #endregion

        #endregion

        #region Properties

        public IPEndPoint ServerIP
        {
            get
            {
                return new IPEndPoint(IPAddress.Parse(SSServerIP), SSServerPort);

            }
            set { _serverIP = value; }
        }

            public static ConfigManager Empty
        {
            get
            {
                return new ConfigManager();
            }
        }

        #region Save Properties
        /// <summary>
        /// 全局的连接数限制
        /// </summary>
        [Save]
        public int TotalThreadLimit 
        {
            get { return _totalThreadLimit; }
            set
            {
                _totalThreadLimit = value;
                this.NotifyPropertyChanged(i => i.ValueList);

            }
        }

        /// <summary>
        /// 中央服务器的IP地址
        /// </summary>
        [Save]
        public int SSServerPort
        {
            get { return _SSServerPort; }
            set 
            { 
                _SSServerPort = value;
                 this.NotifyPropertyChanged(i => i.ValueList);
            }
        }

        /// <summary>
        /// 中央服务器的监听的端口
        /// </summary>
        [Save]
        public string SSServerIP
        {
            get { return _SSServerIP; }
            set { _SSServerIP = value; this.NotifyPropertyChanged(i => i.ValueList); }
        }

        /// <summary>
        /// 每个任务的缓冲区大小
        /// </summary>
        [Save]
        public int BufferSizePerJob
        {
            get { return _bufferSizePerJob; }
            set
            {
                _bufferSizePerJob = value;
                this.NotifyPropertyChanged(i => i.ValueList);
            }
        }

        [Save]
        public int TotalBufferSize
        {
            get { return _totalBufferSize; }
            set
            {
                _totalBufferSize = value;
                this.NotifyPropertyChanged(i => i.ValueList);
            }
        }

        /// <summary>
        /// 每个下载任务的连接数限制
        /// </summary>
        [Save]
        public int JobThreadLimit
        {
            get { return _jobThreadLimit; }
            set
            {
                _jobThreadLimit = value;
                this.NotifyPropertyChanged(i => i.ValueList);
            }
        }


        ///<summary>
        ///SmartThreadPool超时的时间间隔
        ///</summary>
        [Save]
        public int SmartThreadPoolTimeOut
        {
            get { return _smartThreadPoolTimeOut; }
            set
            {
                _smartThreadPoolTimeOut = value;
                this.NotifyPropertyChanged(i => i.ValueList);
            }
        }

        /// <summary>
        /// 定时获取PeerList的时间间隔,以秒为单位
        /// </summary>
        [Save]
        public int GetPeerListInterval
        {
            get { return _getPeerListInterval; }
            set
            {
                _getPeerListInterval = value;
                this.NotifyPropertyChanged(i => i.ValueList);
            }
        }

        /// <summary>
        ///定时清空每个下载任务对应的过时IP列表的时间间隔 ,以秒为单位
        /// </summary>
        [Save]
        public int ClearDisableIpListInterval
        {
            get { return _clearDisableIPListInterval; }
            set
            {
                _clearDisableIPListInterval = value;
                this.NotifyPropertyChanged(i => i.ValueList);
            }
        }

        /// <summary>
        /// 每个节点连接失败后，重试的次数
        /// </summary>
        [Save]
        public int IPRetryCount
        {
            get { return _ipRetryCount; }
            set
            {
                _ipRetryCount = value;
                this.NotifyPropertyChanged(i => i.ValueList);
            }
        }

        /// <summary>
        /// 文件默认保存路径
        /// </summary>
        [Save]
        public string SaveFilePath
        {
            get { return _saveFilePath; }
            set { _saveFilePath = value; }
        }

        /// <summary>
        /// CSsererverPort
        /// </summary>
        [Save]
        public int CSServerPort
        {
            get { return _CSServerPort; }
            set { _CSServerPort = value; }
        }

        #endregion

        


        public IEnumerable<KeyValuePair<string, string>> ValueList
        {
            get
            {
                List<PropertyInfo> saveFieldList = ToSavePropertyList;
                var valueList = new List<KeyValuePair<string, string>>();

                foreach (PropertyInfo info in saveFieldList)
                {
                    object value = info.FastGetValue(this);
                    valueList.Add(new KeyValuePair<string, string>(info.Name, value == null ? "" : value.ToString()));
                }

                return valueList;
            }
        }

        public static List<PropertyInfo> ToSavePropertyList
        {
            get
            {
                if (_toSavePropertyList == null)
                {
                    lock (_syncRoot)
                    {
                        if (_toSavePropertyList == null)
                        {
                            
                            PropertyInfo[] propertyInfos = typeof(ConfigManager).GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

                            List<PropertyInfo> saveFieldList = new List<PropertyInfo>();

                            foreach (PropertyInfo info in propertyInfos)
                            {
                                if (info.GetCustomAttributes(typeof(SaveAttribute), false).Length != 0)
                                {
                                    saveFieldList.Add(info);
                                }
                            }
                            _toSavePropertyList = saveFieldList;
                            return _toSavePropertyList;
                        }
                    }
                }
                return _toSavePropertyList;
            }
        }



        #endregion

        #region Constructor

        private ConfigManager()
        {
            
        }

        #endregion

        #region Methods

        /// <summary>
        /// 
        /// </summary>
        /// <param name="saveFilePath"></param>
        /// <returns></returns>
        public bool Save(string saveFilePath)
        {

            if (!File.Exists(saveFilePath))
            {
                File.CreateText(saveFilePath).Dispose();
            }

            INIClass iniClass = new INIClass(saveFilePath);

            List<PropertyInfo> saveFieldList = ToSavePropertyList;

            foreach (PropertyInfo info in saveFieldList)
            {
                object value = info.FastGetValue(this);
                iniClass.IniWriteValue(SectionName, info.Name, value == null ? "" : value.ToString());
            }

            return false;
        }

        public static ConfigManager Load(string saveFilePath)
        {
            List<PropertyInfo> saveFieldList = ToSavePropertyList;
            ConfigManager configManager = new ConfigManager();
            INIClass iniClass = new INIClass(saveFilePath);

            foreach (PropertyInfo info in saveFieldList)
            {
                string value = iniClass.IniReadValue(SectionName, info.Name);
                configManager.SetProperty(info.Name, value);
            }

            return configManager;
        }

        public void SetProperty(string propertyName, object value)
        {
            PropertyInfo info = this.GetType().GetProperty(propertyName);

            object tryValue;

            string valueStr = value == null ? "" : value.ToString();

            tryValue = TypeHelper.ParseNumber(valueStr, info.PropertyType);

            if (tryValue != null)
            {
                value = tryValue;
            }

            if (info != null && value != null)
            {
                info.FastSetValue(this, value);
            }
            
        }

        #endregion

        

    }
}
